package group.sicher.core.utils;

import group.sicher.core.log.LogManagerUtils;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.springframework.util.FileCopyUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * description: 文件工具类
 * author:dengjinde
 * date:2019/3/18
 */
public class FileUtil {
    protected static Logger logger = LogManagerUtils.getLogger(FileUtil.class);

    public static void copy(InputStream in, String distPath) throws IOException {
        OutputStream out = null;
        try {
            out = new FileOutputStream(distPath);
            IOUtils.copy(in, out);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }
    }


    /**
     * 递归复制文件夹里面的内容到另一个文件夹
     *
     * @param src
     * @param dest
     * @throws IOException
     */
    public static void copyFolder(File src, File dest) throws IOException {
        if (src.isDirectory()) {
            if (!dest.exists()) {
                dest.mkdir();
            }
            String files[] = src.list();
            for (String file : files) {
                File srcFile = new File(src, file);
                File destFile = new File(dest, file);
                copyFolder(srcFile, destFile);
            }
        } else {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new FileInputStream(src);
                out = new FileOutputStream(dest);
                IOUtils.copy(in, out);
            } finally {
                IOUtils.closeQuietly(in);
                IOUtils.closeQuietly(out);
            }
        }
    }

    /**
     * 把要压缩的文件打包成一个zip包
     *
     * @param srcs     要压缩的文件列表
     * @param zipName  压缩的名字
     * @param response
     * @throws IOException
     */
    public static void compress(List<File> srcs, String zipName, HttpServletResponse response) throws IOException {
        byte[] buffer = new byte[8192];
        int length = -1;
        ZipOutputStream zos = null;
        OutputStream os = null;
        try {
            response.reset();
            response.resetBuffer();
            response.setContentType("bin");
            response.addHeader("Content-Disposition", "attachment; filename=\"" + zipName + "\"");
            os = response.getOutputStream();
            zos = new ZipOutputStream(os);
            for (File file : srcs) {
                BufferedInputStream bis = null;
                try {
                    zos.putNextEntry(new ZipEntry(file.getName()));
                    bis = new BufferedInputStream(new FileInputStream(file));
                    while ((length = bis.read(buffer)) != -1) {
                        zos.write(buffer, 0, length);
                    }
                } finally {
                    if (bis != null) {
                        bis.close();
                    }
                    zos.closeEntry();
                }
            }
        } finally {
            if (zos != null) {
                zos.flush();
                zos.close();
            }
        }
    }

    public static void delFile(String path) {
        File dir = new File(path);
        if (dir.exists()) {
            logger.info(String.format("---------------删除文件%s", path));
            try {
                FileUtils.forceDelete(dir);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
            logger.info("---------------删除成功");
        }
    }

//    /**
//     * 将字符串写入文件
//     *
//     * @param content 写入的内容
//     * @param path    文件存放的地址及名称
//     */
//    public static void writeFile(String content, String path) {
//        File file = new File(path);
//        try {
//            FileUtils.writeStringToFile(file, content, "utf-8");
//        } catch (IOException e) {
//            logger.error(e.getMessage(), e);
//        }
//    }

//    /**
//     * 读文件
//     *
//     * @param path 文件的路径
//     * @return 文件的内容
//     */
//    public static String readFile(String path) {
//        File file = new File(path);
//        String fileContent = "";
//        if (file.exists()) {
//            try {
//                fileContent = FileUtils.readFileToString(file, "utf-8");
//            } catch (IOException e) {
//                logger.error(e.getMessage(), e);
//            }
//        } else {
//            logger.error(String.format("###########读取文件:但是文件%s不存在##############", path));
//        }
//        return fileContent;
//    }

    /**
     * 重命名文件或文件夹
     *
     * @param source 源文件
     * @param dest   重命名之后的文件名
     */
    public static void rename(String source, String dest) {
        File file = new File(source);
        if (file.exists()) {
            boolean isRename = file.renameTo(new File(dest));
            if (isRename) {
                logger.info(String.format("将%s重命名为%s", source, dest));

            } else {
                logger.error("#########文件重命名时出错##########");
            }
        }
    }

    /**
     * 附加写文件操作 返回操作是否成功 true成功 false失败
     *
     * @param fileName 文件名
     * @param content  内容
     * @return 附加写文件是否成功 true/false
     */
    public static boolean appendFile(String fileName, String content) {
        boolean result = false;
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(fileName, true);
            fileWriter.append(content);
            fileWriter.flush();
            result = true;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (fileWriter != null) {
                    fileWriter.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        return result;
    }

    /**
     * 下载文件
     *
     * @param path 所要下载的文件路径
     */
    public static void downloadFile(String path, HttpServletResponse response) throws UnsupportedEncodingException {
        File file = new File(path);
        OutputStream outputStream = null;
        try {
            if (!file.exists()) {
                String errorMessage = "The file you are looking for does not exist";
                logger.info(errorMessage);
                outputStream = response.getOutputStream();
                outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8")));
                outputStream.close();
                return;
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                outputStream = null;
            }
        }
        String mimeType = "application/octet-stream";
        logger.info("mimetype : " + mimeType);
        response.setContentType(mimeType);
        String fileName = file.getName();
        fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        InputStream inputStream = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(file));
            FileCopyUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    inputStream = null;
                }
            }
        }
    }

    /**
     * 根据属性名获取属性值
     */
    public static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            return method.invoke(o, new Object[]{});
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }
}
